<?php


namespace App\Services;


use App\Models\Footage;
use App\Models\Product;
use App\Models\Audio;
use App\Models\FootagePart;
use App\Utils\Code;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use App\Utils\VideoUtil;
use Qiniu\Storage\UploadManager;

class FootageService extends BaseService
{
    /**
     * 创建数据
     * @param array $params
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     * @throws \Exception
     */
    public function store(array $params) {
        if (!$this->checkParams($params)){
            throw new \Exception('请求参数验证不通过', Code::PARAMETER_ERROR);
        }
        return DB::transaction(function () use ($params){
            if (!$audio = Audio::find($params['audio_id'])) {
                throw new \Exception('音频存在', Code::EXIST_REPEAT);
            }
            if (Footage::where('name', $params['name'])->exists()) {
                throw new \Exception('名称已经存在', Code::EXIST_REPEAT);
            }
            $model = new Footage();
            $model->name = $params['name'];
            $model->audio_id = $params['audio_id'];
            $model->papper_id = $audio->papper_id;
            $model->save();
            return $this->show($model->id);
        });
    }

    /**
     * 数据信息
     * @param $id
     * @param bool $simple
     * @param bool $abnormal
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     * @throws \Exception
     */
    public function show($id, $abnormal = true) {
        $model = Footage::where('id', $id)->with([
            'audio' => function ($query) {
                $query->with(['papper']);
            },
            'products'
        ])->first();
        if (!$model && $abnormal){
            throw new \Exception('不存在的ID', Code::EMPTY_DATA);
        }
        return $model;
    }

    /**
     * 更新数据
     * @param $id
     * @param array $params
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     * @throws \Exception
     */
    public function update($id, array $params) {
        if (!$this->checkParams($params, true)){
            throw new \Exception('请求参数验证不通过', Code::PARAMETER_ERROR);
        }
        return DB::transaction(function () use ($id, $params){
            $model = $this->show($id);
            if (Footage::where('name', $params['name'])->where('id', '<>', $id)->first()) {
                throw new \Exception('名称已经存在', Code::EXIST_REPEAT);
            }
            $model->name = $params['name'];
            if (isset($params['status']) && is_numeric($params['status'])){
                $model->status = (int)$params['status'];
            }
            $model->save();
            return $model;
        });
    }

    /**
     * 删除数据
     * @param $id
     * @return mixed
     * @throws \Exception
     */
    public function destroy(array $ids = []) {
        if (!$this::$admin) {
            throw new \Exception('你没有权限进行删除', Code::LACK_OF_CONDITIONS);
        }
        if (FootagePart::whereIn('footage_id', $ids)->exists()) {
            throw new \Exception('存在关联的镜头，请先删除关联的镜头', Code::LACK_OF_CONDITIONS);
        }
        return DB::transaction(function () use ($ids) {
            return Footage::whereIn('id', $ids)->delete();
        });
    }

    /**
     * 数据分页
     * @param array $params
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function lists(array $params = []) {
        if (!$this::$admin && empty($params['papper_id']) && empty($params['audio_id'])) {
            throw new \Exception('你没有权限浏览全部镜头组', Code::LACK_OF_CONDITIONS);
        }
        if (isset($params['mode']) && $params['mode'] == 'select') {
            $model = Footage::select(['id', 'name']);
            if (isset($params['papper_id']) && $params['papper_id']) {
                $model = $model->where('papper_id', '=', $params['papper_id']);
            }
            return $model->orderBy('id', 'desc')->get();
        } else {
            $model = Footage::withCount(['parts']);
        }
        if (isset($params['audio_id']) && $params['audio_id']) {
            $model = $model->where('audio_id', '=', $params['audio_id']);
        }
        if (isset($params['papper_id']) && $params['papper_id']) {
            $model = $model->where('papper_id', '=', $params['papper_id']);
        }
        $lists = $model->orderBy('id', 'desc')->paginate(isset($params['per_page']) ? (int)$params['per_page'] : 15);
        return $lists;
    }
    
    /**
     * 合成镜头 弃用
     */
    // public function generateVideo(array $params = []) {
    //     if (!isset($params['footage_id']) || !$params['footage_id']) {
    //         throw new \Exception('镜头组ID不能为空', Code::PARAMETER_ERROR);
    //     }
    //     if (!isset($params['name']) || !$params['name']) {
    //         throw new \Exception('成品名称不能为空', Code::PARAMETER_ERROR);
    //     }
    //     if (Product::where('name', $params['name'])->exists()) {
    //         throw new \Exception('成品名称已经存在', Code::EXIST_REPEAT);
    //     }
    //     $footage = Footage::find($params['footage_id']);
    //     if (!$footage) {
    //         throw new \Exception('不存在的镜头组ID', Code::EMPTY_DATA);
    //     }
    //     if (!$footage->audio->path) {
    //         throw new \Exception('镜头组音频不存在', Code::EMPTY_DATA);
    //     }
    //     return DB::transaction(function () use ($params, $footage){
    //         $audioName = 'audio'.$footage->audio->id.'.mp3';
    //         $basePath = public_path('storage').'/'.$footage->id;
    //         VideoUtil::download_video(
    //             config('app.qiniu_url').'/'.$footage->audio->path, 
    //             $basePath,
    //             $audioName
    //         );
    //         $inputPath = $basePath.'/'.'input.txt';
    //         $file = fopen($inputPath, 'w');
    //         foreach($footage->parts as $part) {
    //             if ($part->path) {
    //                 VideoUtil::download_video(
    //                     config('app.qiniu_url').'/'.$part->path,
    //                     public_path('storage').'/'.$part->footage_id.'/video',
    //                     $part->path
    //                 );
    //                 fwrite($file, 'file video/'.$part->path . PHP_EOL);
    //             }
    //         }
    //         fclose($file);
    //         $audioPath = $basePath.'/'.$audioName;
    //         $outputPath = $basePath.'/'.'output.mp4';
    //         // $command = "ffmpeg -f concat -safe 0 -i {$inputPath} -c:v libx264 {$outputPath}";
    //         // $command = "ffmpeg -f concat -safe 0 -i {$inputPath} -i {$audioPath} -c copy -map 0:v -map 1:a {$outputPath}";
    //         $command = "ffmpeg -f concat -safe 0 -i {$inputPath} -i {$audioPath} -c:v libx264 -c:a aac -strict experimental -map 0:v -map 1:a -r 30 -shortest {$outputPath}";
    //         return $command;
    //         exec($command, $output, $return_var);
    //         if ($return_var !== 0) {
    //             return "合并视频处理失败";
    //         }
    //         $token = (new QiniuService())->getToken([]);
    //         $uploadMgr = new UploadManager();
    //         $data = $uploadMgr->putFile($token, null, $outputPath);
    //         $model = new Product();
    //         $model->type = 1;
    //         $model->name = $params['name'];
    //         $model->path = $data[0]['key'];
    //         $model->footage_id = $footage->id;
    //         $model->papper_id = $footage->papper_id;
    //         $model->save();
    //         return $model;
    //     });
    // }

    /**
     * 验证参数
     * @param array $params
     * @param bool $isUpdate
     * @return array
     * @throws \Exception
     */
    private function checkParams(array $params, $isUpdate = false){
        $rules = [
            'name' => ['bail', 'required', 'string', 'between:1,50'],
            'audio_id' => ['bail', 'required', 'integer'],
            'status' => ['bail', 'nullable', 'integer'],
        ];
        if ($isUpdate){
            // 删除必选条件
            foreach ($rules as $field => &$rule){
                if (isset($rule[1]) && $rule[1] == 'required') {
                    unset($rule[1]);
                }
            }
        }
        $validator = Validator::make($params, $rules, [], [
            'name' => '名称',
            'audio_id' => '音频ID',
            'status' => '状态'
        ]);
        if ($validator->fails()) {
            throw new \Exception($validator->errors()->first(), Code::PARAMETER_ERROR);
        }
        return $params;
    }
}
